package com.yanqu.road.server.gameplayer.module.activity.businessreunion;

import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.businessreunion.BusinessReunionBindData;
import com.yanqu.road.entity.activity.businessreunion.BusinessReunionData;
import com.yanqu.road.entity.activity.businessreunion.RecallUserInfo;
import com.yanqu.road.entity.activity.oldplayerreturn.OldPlayerReturnUserData;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eSystemId;
import com.yanqu.road.entity.log.LogBusinessReunion;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.servercenter.ServerInfo;
import com.yanqu.road.logic.bussiness.activity.BusinessReunionBusiness;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.pb.activity.BusinessReunionProto;
import com.yanqu.road.pb.player.PlayerProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.oldplayerreturn.OldPlayerReturnModule;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.manger.activity.businessreunion.BusinessReunionActivityMgr;
import com.yanqu.road.server.manger.activity.businessreunion.BusinessReunionMgr;
import com.yanqu.road.server.manger.activity.businessreunion.ReunionConfig;
import com.yanqu.road.server.manger.activity.oldplayerreturn.OldPlayerReturnMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.pb.PlayerPb;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.CrossProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author ：zfr
 * @date ：2022/4/18 10:42
 */
public class BusinessReunionActivityModule extends GeneralModule {
    private BusinessReunionBindData bindData;

    public BusinessReunionActivityModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        ActivityInfo activityInfo = BusinessReunionActivityMgr.getActivityInfo();
        if (activityInfo == null) {
            return true;
        }
        reloadActivityData(activityInfo.getActivityId());
        return true;
    }

    /**
     * 初始化数据
     * @param activityId
     */
    private synchronized void initUserData(int activityId) {
        BusinessReunionData businessReunionData = BusinessReunionMgr.getBusinessReturnData(player.getUserId());
        if (businessReunionData != null && businessReunionData.getActivityId() == activityId) {
            return;
        }
        //召回码
        String recallCode = BusinessReunionActivityMgr.generateRecallCode(player.getUserId());
        businessReunionData = new BusinessReunionData();
        businessReunionData.setPlayerId(player.getUserId());
        businessReunionData.setActivityId(activityId);
        businessReunionData.setRecallCode(recallCode);
        businessReunionData.setInsertOption();
        BusinessReunionMgr.addData(businessReunionData);
    }

    /**
     * 填写召回码
     * @param recallCode 召回码
     * @return ret
     */
    public int writeRecallCode(String recallCode) {
        ActivityInfo activityInfo = BusinessReunionActivityMgr.getActivityInfo();
        if (activityInfo == null) {
            return GameErrorCode.E_ACTIVITY_NO_FOUND; //活动不存在
        }
        OldPlayerReturnUserData userData = OldPlayerReturnMgr.getUserData(player.getUserId());
        if (userData == null) {
            return GameErrorCode.E_PLAYER_RETURN_NOT_RETURN_ROLE; //不是回归玩家
        }
        int ret = player.getModule(OldPlayerReturnModule.class).checkReturnRoleIsEffective(userData);
        if (ret != 0) {
            return GameErrorCode.E_PLAYER_RETURN_NOT_RETURN_ROLE; //不是回归玩家
        }
        List<Long> userInfoIdList = getUserInfoByRecallCode(recallCode);
        if (userInfoIdList == null) {
            return GameErrorCode.E_BUSINESS_REUNION_RECALL_CODE_ERROR;  //召回码有误
        }
        long serverId = userInfoIdList.get(0);
        long playerId = userInfoIdList.get(1);
        ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);
        if (serverInfo == null || !serverInfo.isOpen()) {
            return GameErrorCode.E_BUSINESS_REUNION_RECALL_CODE_ERROR;  //召回码有误
        }
        if (playerId == player.getUserId()) {
            BusinessReunionData businessReturnData = BusinessReunionMgr.getBusinessReturnData(player.getUserId());
            if (businessReturnData == null || !Objects.equals(recallCode, businessReturnData.getRecallCode())) {
                return GameErrorCode.E_BUSINESS_REUNION_RECALL_CODE_ERROR; //召回码有误
            }
            return GameErrorCode.E_BUSINESS_REUNION_WRITE_SELF_CODE; //不能填写自己的召回码
        }
        if (bindData != null && bindData.isBind()) {
            return GameErrorCode.E_BUSINESS_REUNION_ALREADY_BIND; //已经填写过
        }
        if (bindData == null) {
            initBindData(activityInfo.getActivityId());
        }
        if (serverId == GameServer.getInstance().getServerId()) {
            PlayerProto.PlayerBaseTempMsg.Builder playerBaseTempMsg = PlayerPb.parsePlayerBaseTempMsg(player.getUserInfo());
            UserBaseInfo userBaseInfo = PlayerBasePb.parseBaseUserInfo(playerBaseTempMsg.build());
            ret = BusinessReunionMgr.recallBind(playerId, player.getUserId(), userBaseInfo, recallCode);
            if (ret == 0) {
                recallBindSuccess(recallCode);
            }
            return ret;
        }
        bindData.setPreBindRecallCode(recallCode);
        BusinessReunionProto.WriteRecallCodeReqCrossMsg.Builder reqCrossMsg = BusinessReunionProto.WriteRecallCodeReqCrossMsg.newBuilder();
        reqCrossMsg.setRecallCode(recallCode);
        reqCrossMsg.setReqBindServerId(serverId);
        reqCrossMsg.setReqBindUserId(playerId);
        reqCrossMsg.setRecallUserInfo(PlayerPb.parsePlayerBaseTempMsg(player.getUserInfo()));
        player.sendPacket(CrossProtocol.C_CROSS_RECALL_BIND, reqCrossMsg);
        return 0;
    }

    /**
     * 初始化召回绑定状态
     * @param activityId 活动id
     */
    private void initBindData(int activityId) {
        bindData = new BusinessReunionBindData();
        bindData.setActivityId(activityId);
        bindData.setUserId(player.getUserId());
        bindData.setInsertOption();
    }

    /**
     * 根据召回码解析出 serverId(index:0) userId(index:1)
     * @param recallCode 召回码
     * @return list 解析有问题 返回null
     */
    public List<Long> getUserInfoByRecallCode(String recallCode) {
        List<Long> list = new ArrayList<>();
        if (!BusinessReunionMgr.checkStringAllInDigits(recallCode)) {
            return null;
        }
        long userId = BusinessReunionMgr.sixtyTwoToTenHex(recallCode);
        String userIdStr = String.valueOf(userId);
        if (userIdStr.length() != 15) {
            return null;
        }
        long serverId = Long.parseLong(userIdStr.substring(0, 8));
        list.add(0, serverId);
        list.add(1, userId);
        return list;
    }

    /**
     * 恢复预召回状态
     */
    public void resetPreBind() {
        if (bindData == null) {
            return;
        }
        bindData.resetPreBind();
    }

    /**
     * 召回绑定成功
     * @param recallCode 召回码
     */
    public void recallBindSuccess(String recallCode) {
        if (bindData == null) {
            return;
        }
        if (!bindData.getRecallCode().isEmpty()) {
            return;
        }
        //跟预存的召回码不一致
        if (!bindData.getPreBindRecallCode().isEmpty() && !Objects.equals(recallCode, bindData.getPreBindRecallCode())) {
            log.error("bind recallCode and preRecallCode diff, recallCode:{}, preRecallCode:{}, playerId:{}",
                    recallCode, bindData.getRecallCode(), player.getUserId());
        }
        String reward = "";
        ReunionConfig config = BusinessReunionActivityMgr.getConfig();
        if (config != null) {
            reward = config.getBindReward();
        }
        bindData.recallBindSuccess(recallCode);
        player.getModule(CurrencyModule.class).addCurrency(reward, eLogMoneyType.BusinessReunion, eLogMoneyType.BusinessReunionBindReward);
        BusinessReunionProto.WriteRecallCodeRespMsg.Builder respMsg = BusinessReunionProto.WriteRecallCodeRespMsg.newBuilder();
        respMsg.setReward(reward);
        respMsg.setRet(0);
        player.sendPacket(ClientProtocol.U_BUSINESS_REUNION_WRITE_RECALL_CODE, respMsg);
        if (bindData.getAddVipExp() > 0) {
            syncBindPlayerAddVipExp();
        }
        syncBindData();
        long bindPlayerId = 0;
        List<Long> userInfoIdList = getUserInfoByRecallCode(bindData.getRecallCode());
        if (userInfoIdList != null) {
            bindPlayerId = userInfoIdList.get(1);
        }

        AutoLogMgr.add(new LogBusinessReunion(bindData.getActivityId(), bindData.getUserId(), bindData.getRecallCode(), bindPlayerId, reward));
    }

    /**
     * 增加vip经验
     * @param addVipExp
     */
    public synchronized void addVipExp(long addVipExp) {
        if (bindData == null) {
            return;
        }
        if (!bindData.isBind()) {
            return;
        }
        if (bindData.getRecallCode().isEmpty()) {
            bindData.setPreAddVipExp((int) (bindData.getPreAddVipExp() + addVipExp));
            return;
        }
        bindData.setAddVipExp((int) (bindData.getAddVipExp() + addVipExp));
        syncBindPlayerAddVipExp();
    }

    public void syncBindPlayerAddVipExp() {
        List<Long> userInfoIdList = getUserInfoByRecallCode(bindData.getRecallCode());
        if (userInfoIdList == null) {
            return;
        }
        long serverId = userInfoIdList.get(0);
        long playerId = userInfoIdList.get(1);
        ServerInfo serverInfo = ServerListMgr.getServerInfo(serverId);
        if (serverInfo == null || !serverInfo.isOpen()) {
            return;
        }
        if (GameServer.getInstance().getServerId() == serverId) {
            BusinessReunionMgr.syncAddVipExp(playerId, player.getUserId(), bindData.getAddVipExp());
            return;
        }
        BusinessReunionProto.SyncBindPlayerAddVipExpMsg.Builder syncMsg = BusinessReunionProto.SyncBindPlayerAddVipExpMsg.newBuilder();
        syncMsg.setRecallUserId(player.getUserId());
        syncMsg.setSyncToServerId(serverId);
        syncMsg.setSyncToUserId(playerId);
        syncMsg.setAddVipExp(bindData.getAddVipExp());
        player.sendPacket(CrossProtocol.C_CROSS_SYNC_TO_BIND_PLAYER_ADD_VIP_EXP, syncMsg);
    }

    @Override
    public boolean afterLoadData() {
        return false;
    }

    @Override
    public boolean saveData() {
        if (bindData != null) {
            if (bindData.isInsertOption()) {
                return BusinessReunionBusiness.addBindData(bindData);
            } else if (bindData.isUpdateOption()) {
                return BusinessReunionBusiness.updateBindData(bindData);
            }
        }
        return true;
    }

    public void reloadActivityData(int activityId) {
        bindData = BusinessReunionBusiness.getBusinessReunionBindData(player.getUserId(), activityId);
        if (SystemOpenMgr.systemOpen(player, eSystemId.BusinessReunion.getValue())) {
            BusinessReunionData businessReunionData = BusinessReunionMgr.getBusinessReturnData(player.getUserId());
            if (businessReunionData == null) {
                initUserData(activityId);
            }
            syncActivityData();
        }
    }

    public void initSystem(){
        ActivityInfo activityInfo = BusinessReunionActivityMgr.getActivityInfo();
        if (activityInfo == null) {
            return;
        }
        initUserData(activityInfo.getActivityId());
        syncActivityData();
    }

    @Override
    public void afterLogin() {
        BusinessReunionData businessReunionData = BusinessReunionMgr.getBusinessReturnData(player.getUserId());
        if (businessReunionData != null) {
            BusinessReunionMgr.addIntegral(businessReunionData);
        }
        syncActivityData();
    }

    public void syncActivityData() {
        ActivityInfo activityInfo = BusinessReunionActivityMgr.getActivityInfo();
        if (activityInfo == null) {
            return;
        }
        if (bindData != null && bindData.getActivityId() == activityInfo.getActivityId()) {
            syncBindData();
        }
        BusinessReunionData businessReunionData = BusinessReunionMgr.getBusinessReturnData(player.getUserId());
        if (businessReunionData != null && businessReunionData.getActivityId() == activityInfo.getActivityId()) {
            syncData(businessReunionData);
        }
    }

    private void syncBindData() {
        BusinessReunionProto.BusinessReunionBindSyncMsg.Builder syncMsg = BusinessReunionProto.BusinessReunionBindSyncMsg.newBuilder();
        syncMsg.setActivityId(bindData.getActivityId());
        syncMsg.setRecallCode(bindData.getRecallCode());
        syncMsg.setAddVipExp(bindData.getAddVipExp());
        player.sendPacket(ClientProtocol.U_BUSINESS_REUNION_BIND_SYNC, syncMsg);
    }

    private void syncData(BusinessReunionData businessReunionData) {
        BusinessReunionProto.BusinessReunionDataSyncMsg.Builder syncMsg = BusinessReunionProto.BusinessReunionDataSyncMsg.newBuilder();
        syncMsg.setActivityId(businessReunionData.getActivityId());
        syncMsg.setRecallCode(businessReunionData.getRecallCode());
        for (RecallUserInfo recallUserInfo : businessReunionData.getRecallUserInfos()) {
            BusinessReunionProto.RecallUserInfoMsg.Builder builder = BusinessReunionProto.RecallUserInfoMsg.newBuilder();
            builder.setRecallUserId(recallUserInfo.getRecallUserId());
            builder.setRecallTime(recallUserInfo.getRecallTime());
            builder.setBindAddIntegral(recallUserInfo.getAddBindIntegral());
            builder.setVipExpAddIntegral(recallUserInfo.getAddVipIntegral());
            builder.setRecallUserInfo(PlayerBasePb.parsePlayerBaseTempMsg(recallUserInfo.getUserBaseInfo()));
            syncMsg.addRecallUserInfo(builder);
        }
        player.sendPacket(ClientProtocol.U_BUSINESS_REUNION_DATA_SYNC, syncMsg);
    }

    public void resetReunionBind() {
        if (bindData == null) {
            return;
        }
        bindData.resetBind();
        syncBindData();
    }
}
